<?php
namespace UHU\output;
interface API
{
	public static function process_Residents(\UHU\SecondLife\Residents $Residents);
	public static function process_Achievements(\UHU\SecondLife\Agni\Achievements $Achievements);
	public static function process_hCalendar(\UHU\microformats\hCalendar $hCalendar);
}

namespace UHU\output\API;

abstract class basic implements \ArrayAccess, \UHU\output\API
{
	protected $Residents;
	protected $Achievements;
	protected $vEvents;
	protected $array = array();
	public function __construct()
	{
		if(class_exists('\UHU\SecondLife\Residents'))
		{
			$this->Residents = new \UHU\SecondLife\Residents;
		}
		if(class_exists('\UHU\SecondLife\Agni\Achievements'))
		{
			$this->Achievements = new \UHU\SecondLife\Agni\Achievements;
		}
		if(class_exists('\UHU\microformats\hCalendar'))
		{
			$this->vEvents = new \UHU\microformats\hCalendar;
		}
	}
	public function offsetExists($offset)
	{
		return false;
	}
	public function offsetUnset($offset)
	{}
	public function offsetGet($offset)
	{
		return null;
	}
	public function offsetSet($offset,$val)
	{
		if($val instanceof \UHU\SecondLife\Resident)
		{
			$this->Residents[] = $val;
		}
		else if($val instanceof \UHU\SecondLife\Agni\Achievement)
		{
			$this->Achievements[] = $val;
		}
		else if($val instanceof \UHU\microformats\hCalendar\vEvent)
		{
			$this->vEvents[] = $val;
		}
		else if($val instanceof \UHU\microformats\hCalendar_pool)
		{
			foreach($val as $k=>$v)
			{
				$this[$k] = $v;
			}
		}
		else if($val instanceof \UHU\microformats\hCalendar)
		{
			foreach($val as $k=>$v)
			{
				$this[$k] = $v;
			}
		}
		else if($val instanceof \UHU\SecondLife\Agni\Achievements)
		{
			foreach($val as $k=>$v)
			{
				$this[$k] = $v;
			}
		}
		else if(is_array($val))
		{
			foreach($val as $k=>$v)
			{
				if(is_array($v) || is_object($v))
				{
					throw new \InvalidArgumentException('Unsupported data (arrays and objects not allowed in API data).');
				}
				else
				{
					$this->array[$k] = $v;
				}
			}
		}
		else
		{
			throw new \InvalidArgumentException('Unsupported data.');
		}
	}
	public function __toString()
	{
			try
			{
		$doc_sections = array();
		if(isset($this->Residents) && $this->Residents->count() > 0)
		{
			$doc_sections[] = implode("\n",static::process_Residents($this->Residents));
		}
		if(isset($this->Achievements) && $this->Achievements->count() > 0)
		{
			$doc_sections[] = implode("\n",static::process_Achievements($this->Achievements));
		}
		if(isset($this->vEvents) && $this->vEvents->count() > 0)
		{
			$doc_sections[] = implode("\n",static::process_hCalendar($this->vEvents));
		}
		if(empty($this->array) === false)
		{
			$doc_sections[] = implode("\n",static::process_Array($this->array));
		}
			}
			catch(\Exception $e)
			{
				return (string)$e;
			}
		return implode("\n\n",$doc_sections);
	}
	public function output($lifetime=null)
	{
		header('Content-Type:' . static::MIME);
		\UHU\output($this,$lifetime);
	}
}

class text extends basic
{
	const MIME = 'text/plain';
	protected static function uri_MIME($uri)
	{
		switch(strtolower(substr($uri,strrpos($uri,'.') + 1)))
		{
			case 'jpeg':
			case 'jpg':
			case 'jpe':
				return 'image/jpeg';
			break;
			case 'png':
				return 'image/png';
			default:
				return 'text/plain';
			break;
		}
	}
	public static function process_Residents(\UHU\SecondLife\Residents $Residents)
	{
		$doc = array();
		foreach($Residents as $Resident)
		{
			list($first,$last) = explode(' ',$Resident->fn());
			$doc[] =
				'BEGIN:VCARD' . "\n" .
				'VERSION:3.0' . "\n" .
				'N:' . $last . ';' . $first . "\n" .
				'FN:' . $Resident->fn() . "\n" .
				'UID:' . $Resident->uid() . "\n" .
				'END:VCARD';
		}
		return $doc;
	}
	public static function process_Achievements(\UHU\SecondLife\Agni\Achievements $Achievements)
	{
		$doc = array();
		$doc[] =
			'BEGIN:VCALENDAR' . "\n" .
			'PRODID:-//UHU//SL-Achievements//EN' . "\n" .
			'VERSION:2.0';
		foreach($Achievements as $Achievement)
		{
			$foo =
				'BEGIN:VEVENT' . "\n" .
				'UID:' . $Achievement->uid() . "\n" .
				'DTSTART:' . $Achievement->last_action()->ical() . "\n" .
				'SUMMARY:' . $Achievement->title() . "\n" .
				'DESCRIPTION:' . $Achievement->description() . "\n" .
				'CATEGORIES:' . $Achievement->category_title() . "\n" .
				'ATTACH;FMTTYPE=' . static::uri_MIME($Achievement->image()->url()) . ':' . $Achievement->image()->url() . "\n";
			if(method_exists($Achievement,'requirement') === true)
			{
				$foo .= 'REQUIREMENT:' . (string)$Achievement->requirement() . ";\n";
			}
			$foo .= 'ORGANIZER;UID=' . $Achievement->author_uid() . 
				':CN=' . $Achievement->author()->fn() . ':';
			if($Achievement->author() instanceof \UHU\microformats\hCard\photo)
			{
				$foo .= 'PHOTO=' . $Achievement->author()->photo() . ':';
			}
			if($Achievement->author() instanceof \UHU\microformats\hCard\url)
			{
				$foo .= 'URL=' . $Achievement->author()->url() . ':';
			}
			$foo .= "\n";
			if($Achievement->parents()->count() > 0)
			{
				$parents = array();
				foreach($Achievement->parents() as $parent)
				{
					$parents[] = $parent->uid();
				}
				$foo .= 'RELATEDTO;RELTYPE=PARENT:' . implode(';',$parents) . "\n";
			}
			if($Achievement->children()->count() > 0)
			{
				$children = array();
				foreach($Achievement->children() as $child)
				{
					$children[] = $child->uid();
				}
				$foo .= 'RELATEDTO;RELTYPE=CHILD:' . implode(';',$children) . "\n";
			}
			if($Achievement->siblings()->count() > 0)
			{
				$siblings = array();
				foreach($Achievement->siblings() as $sibling)
				{
					$siblings[] = $sibling->uid();
				}
				$foo .= 'RELATEDTO;RELTYPE=SIBLING:' . implode(';',$siblings) . "\n";
			}
			$foo .= 'END:VEVENT';
			$doc[] = $foo;
		}
		$doc[] = 'END:VCALENDAR' . "\n";
		return $doc;
	}
	public static function process_hCalendar(\UHU\microformats\hCalendar $hCalendar)
	{
		$doc = array();
		$doc[] =
			'BEGIN:VCALENDAR' . "\n" .
			'VERSION:2.0' . "\n" .
			'CALSCALE:GREGORIAN';
		foreach($hCalendar as $vEvent)
		{
			$foo =
				'BEGIN:VEVENT' . "\n";
			if($vEvent instanceof \UHU\microformats\hCalendar\uid)
			{
				$uid = (string)$vEvent->uid();
				if(empty($uid) === false)
				{
					$foo .= 'UID:' . $uid . "\n";
				}
				unset($uid);
			}
			$foo .=
				'SUMMARY:' . (string)$vEvent->summary()      . "\n" .
				'DTSTART:' . (string)$vEvent->dtstart()->ical() . "\n";
			if($vEvent instanceof \UHU\microformats\hCalendar\dtend && $vEvent->dtend() instanceof \UHU\moment)
			{
				$foo .= 'DTEND:' . (string)$vEvent->dtend()->ical() . "\n";
			}
			if($vEvent instanceof \UHU\microformats\hCalendar\url)
			{
				$url = (string)$vEvent->url();
				if(empty($url) === false)
				{
					$foo .= 'URL:' . $url . "\n";
				}
				unset($url);
			}
			if($vEvent instanceof \UHU\microformats\hCalendar\category)
			{
				$category = (string)$vEvent->category();
				if(empty($category) === false)
				{
					$foo .= 'CATEGORIES:' . $category . "\n";
				}
			}
			if($vEvent instanceof \UHU\microformats\hCalendar\description)
			{
				$description = (string)$vEvent->description();
				if(empty($description) === false)
				{
					$foo .= 'DESCRIPTION:'. $description . "\n";
				}
			}
			if($vEvent instanceof \UHU\microformats\hCalendar\organizer)
			{
				if($vEvent->organizer() instanceof \UHU\microformats\hCard\fn)
				{
					$foo .= 'ORGANIZER;CN=' . $vEvent->organizer()->fn() . ":\n";
				}
			}
			if($vEvent instanceof \UHU\microformats\hCalendar\location)
			{
				if($vEvent->location() instanceof \UHU\microformats\hCard\fn)
				{
					$foo .= 'LOCATION:' . $vEvent->location()->fn();
					if($vEvent->location() instanceof \UHU\microformats\hCard\url)
					{
						$foo .= ' ' . $vEvent->location()->url();
					}
					$foo .= "\n";
				}
			}
			$foo .= 'END:VEVENT';
			$doc[] = $foo;
		}
		$doc[] = 'END:VCALENDAR' . "\n";
		return $doc;
	}
	public static function process_Array(array $data)
	{
		$doc = array('---');
		foreach($data as $k=>$v)
		{
			if(is_array($v) || is_object($v))
			{
				throw new \InvalidArgumentException('Unsupported data (arrays and objects not allowed in API data).');
			}
			else
			{
				$doc[] = $k . ":\t" . (string)$v;
			}
		}
		return $doc;
	}
}
?>